package ro.msg.quiz.view;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;

import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import ro.msg.quiz.controller.Controller;
import ro.msg.quiz.repository.Quiz;

/**
 * Create the dialog.
 * 
 * @author Adorjan
 */
public class AddNewQuiz extends JDialog {
	private static AddNewQuiz instance = null;
	private static int NOT_ASSIGNED = -1;
	private final JPanel buttonPane = new JPanel();
	private final JButton btnBack = new JButton("Back");
	private final JButton nextButton = new JButton("Next");
	private final JButton cancelButton = new JButton("Cancel");
	private final JButton btnFinish = new JButton("Finish");
	private AddQuizTitlePanel addQuizTitlePanel;
	private AddQuizSelectQuestions addQuizSelectQuestions;
	private Controller ctrl;
	private int repoLength;
	private ArrayList<Integer> numbers; // 0-repoLength
	private ArrayList<Integer> questionIds = new ArrayList<Integer>();
	private int quizId;
	private Quiz quiz = new Quiz();

	/**
	 * The dialog's constructor
	 * 
	 * @author Adorjan
	 */
	private AddNewQuiz(Controller controller) {
		this.quizId = NOT_ASSIGNED;
		setTitle("Add new questionnaire");
		init(controller);
	}

	/**
	 * Constructor with a quizId
	 * 
	 * @param controller
	 * @param quiz
	 */
	private AddNewQuiz(Controller controller, Integer quiz) {
		this.quizId = quiz;
		setTitle("Add new questionnaire");
		init(controller);
	}

	/**
	 * Initializes the dialog
	 * 
	 * @param controller
	 */
	private void init(Controller controller) {
		this.ctrl = controller;

		// preparing the numbers for the random feature
		repoLength = ctrl.getQuestionList().size();
		numbers = new ArrayList<Integer>();
		for (int i = 0; i < repoLength; i++)
			numbers.add(i);

		setResizable(false);
		setBounds(100, 100, 450, 243);
		getContentPane().setLayout(new BorderLayout());

		buttonPane.setLayout(new FlowLayout(FlowLayout.RIGHT));
		getContentPane().add(buttonPane, BorderLayout.SOUTH);

		addQuizTitlePanel = new AddQuizTitlePanel();

		// if an existing quiz was given
		if (quizId != NOT_ASSIGNED) {
			quiz = ctrl.getFromQuizList(quizId);
			addQuizTitlePanel.getTextField().setText(quiz.getQuizName());
			questionIds = ctrl.getQuestions(quizId);
			nextButton.setEnabled(true);
		} else
			nextButton.setEnabled(false);

		addQuizSelectQuestions = new AddQuizSelectQuestions(ctrl, questionIds);
		getContentPane().add(addQuizSelectQuestions, BorderLayout.CENTER);
		addQuizSelectQuestions.setVisible(false);
		addQuizSelectQuestions.setBounds(0, 0, 450, 301);
		getContentPane().add(addQuizTitlePanel, BorderLayout.CENTER);

		btnBack.setHorizontalAlignment(SwingConstants.LEFT);
		buttonPane.add(btnBack);
		btnBack.setVisible(false);
		/**
		 * Back button's action listener
		 */
		btnBack.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				setBounds(100, 100, 450, 243);
				addQuizTitlePanel.setVisible(true);
				getContentPane().remove(addQuizSelectQuestions);
				btnBack.setVisible(false);
				btnFinish.setVisible(false);
				nextButton.setVisible(true);
			}
		});

		/**
		 * Cancel button's action listener
		 */
		cancelButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				dispose();
			}
		});
		cancelButton.setActionCommand("Cancel");
		buttonPane.add(cancelButton);

		/**
		 * Finish button's action listener
		 */
		btnFinish.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (addQuizSelectQuestions.getNoOfQuestions() == 0) {
					JOptionPane.showMessageDialog(null,
							"Select atleast 1 question to add!", "Oops!",
							JOptionPane.WARNING_MESSAGE);
				} else {
					// add the quiz to the repository
					quiz.setQuizName(addQuizTitlePanel.getTextField().getText()
							.toString());
					// if it's add mode
					if (quizId == NOT_ASSIGNED)
						quizId = ctrl.getLastIdQuizRepo() + 1;
					else
						// remove the old record
						ctrl.removeQuiz(quizId);
					quiz.setId(quizId);
					ctrl.addQuiz(quiz);
					// make the relations
					questionIds = new ArrayList<Integer>();
					for (int i = 0; i < addQuizSelectQuestions.getTable()
							.getRowCount(); i++) {
						if ((Boolean) addQuizSelectQuestions.getTable()
								.getModel().getValueAt(i, 0))
							questionIds.add((Integer) addQuizSelectQuestions
									.getTable().getModel().getValueAt(i, 2));
					}
					ctrl.addQuestionsQuiz(quizId, questionIds);
					dispose();
					// show it in the table
				}
			}
		});
		buttonPane.add(btnFinish);
		btnFinish.setVisible(false);

		/**
		 * Next button's action listener
		 */
		nextButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				setBounds(100, 100, 450, 351);
				getContentPane().add(addQuizSelectQuestions);
				addQuizSelectQuestions.setVisible(true);
				addQuizTitlePanel.setVisible(false);
				btnBack.setVisible(true);
				btnFinish.setVisible(true);
				nextButton.setVisible(false);

			}
		});
		nextButton.setActionCommand("OK");
		buttonPane.add(nextButton);
		getRootPane().setDefaultButton(nextButton);

		/**
		 * Textfield's (first panel) document listener
		 */
		addQuizTitlePanel.getTextField().getDocument()
				.addDocumentListener(new DocumentListener() {
					@Override
					public void changedUpdate(DocumentEvent e) {
						changed();
					}

					@Override
					public void removeUpdate(DocumentEvent e) {
						changed();
					}

					@Override
					public void insertUpdate(DocumentEvent e) {
						changed();
					}

					public void changed() {
						if (addQuizTitlePanel.getTextField().getText().trim()
								.isEmpty()) {
							nextButton.setEnabled(false);
						} else {
							nextButton.setEnabled(true);
						}

					}
				});

		/**
		 * Textfield's (second panel) document listener
		 */
		addQuizSelectQuestions.getTextField().getDocument()
				.addDocumentListener(new DocumentListener() {

					@Override
					public void removeUpdate(DocumentEvent e) {
						changed();

					}

					@Override
					public void insertUpdate(DocumentEvent e) {
						changed();

					}

					@Override
					public void changedUpdate(DocumentEvent e) {
						changed();

					}

					/**
					 * if a number is introduced in the textbox, it selects
					 * randomly the number of lines if the textbox gets empty,
					 * it deselects all the checkboxes
					 */
					public void changed() {
						JTextField textField = addQuizSelectQuestions
								.getTextField();
						JTable table = addQuizSelectQuestions.getTable();

						if (textField.getText().toString().equals("")) {
							deselectAll();

						} else {
							// first step: clean what was selected before
							deselectAll();

							int noOfSelections = Integer.parseInt(textField
									.getText());
							// if the input number is higher than the repository
							// size
							if (noOfSelections > repoLength) {
								noOfSelections = repoLength;
								for (int i = 0; i < noOfSelections; i++) {
									table.setValueAt(true, i, 0);
								}
							}
							// normal case
							else {
								if (noOfSelections != repoLength)
									Collections.shuffle(numbers);
								for (int i = 0; i < noOfSelections; i++) {
									table.setValueAt(true, numbers.get(i), 0);
								}
							}
						}
					}

					/**
					 * deselects all checkboxes in the table
					 */
					public void deselectAll() {
						for (int i = 0; i < repoLength; i++) {
							addQuizSelectQuestions.getTable().getModel()
									.setValueAt(false, i, 0);
						}
					}
				});
	}

	/**
	 * makes an instance of this class
	 * 
	 * @param controller
	 * @return
	 */
	public static AddNewQuiz getInstance(Controller controller) {
		if (instance == null) {
			instance = new AddNewQuiz(controller);
		}
		return instance;
	}

	/**
	 * makes an instance of this class with a given question's id
	 * 
	 * @param controller
	 * @return
	 */
	public static AddNewQuiz getInstance(Controller controller, Integer quiz) {
		if (instance == null) {
			instance = new AddNewQuiz(controller, quiz);
		}
		return instance;
	}

	/**
	 * resets the instance
	 */
	public static void reset() {
		instance = null;
	}

}
